home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / LinAlg 3.1 / LinAlg / vector.cc < prev    next >
Encoding:
Text File  |  1995-12-21  |  4.9 KB  |  189 lines  |  [TEXT/ALFA]

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *            Linear Algebra Package
  6.  *
  7.  *        Basic Linear Algebra operations, level 1 & 2
  8.  *             concerning specifically vectors
  9.  *
  10.  * The present file is concerned with the operations which either
  11.  *    - specifically defined for vectors, such as norms
  12.  *     - some BLAS 1 & 2 operations that can be implemented more 
  13.  *      efficiently than generic operations on n*1 matrices
  14.  *
  15.  * $Id: vector.cc,v 3.0 1995/01/04 15:49:34 oleg Exp $
  16.  *
  17.  ************************************************************************
  18.  */
  19.  
  20. #include "LinAlg.h"
  21. #include <math.h>
  22. #include "builtin.h"
  23.  
  24. /*
  25.  *------------------------------------------------------------------------
  26.  *               Specific vector constructors
  27.  */
  28.  
  29. #include <stdarg.h>
  30.             // Make a vector and assign initial values
  31.             // Argument list should contain DOUBLE values
  32.             // to assign to vector elements. The list must
  33.             // be terminated by the string "END"
  34.             // Example: Vector foo(1,3,0.0,1.0,1.5,"END");
  35. Vector::Vector(const int lwb, const int upb, double iv1, ... )
  36.   : Matrix(lwb,upb,1,1)
  37. {
  38.   va_list args;
  39.   va_start(args,iv1);            // Init 'args' to the beginning of
  40.                     // the variable length list of args
  41.   register int i;
  42.   (*this)(lwb) = iv1;
  43.   for(i=lwb+1; i<=upb; i++)
  44.     (*this)(i) = (double)va_arg(args,double);
  45.  
  46.   assure( strcmp((char *)va_arg(args,char *),"END") == 0,
  47.      "Vector: argument list must be terminated by \"END\" ");
  48. }
  49.  
  50.                 // Resize the vector for a specified number
  51.                 // of elements, trying to keep intact as many
  52.                 // elements of the old vector as possible.
  53.                 // If the vector is expanded, the new elements
  54.                 // will be zeroes
  55. void Vector::resize_to(const int lwb, const int upb)
  56. {
  57.   is_valid();
  58.   const int old_nrows = nrows;
  59.   assure( (nrows = upb-lwb+1) > 0,
  60.      "can't resize vector to a non-positive number of elems" );
  61.  
  62.   row_lwb = lwb;
  63.   if( old_nrows == nrows )
  64.     return;                    // The same number of elems
  65.  
  66.   nelems = nrows;
  67.  
  68.                 // If the vector is to grow, reallocate
  69.                 // and clear the newly added elements
  70.   if( nrows > old_nrows )
  71.     elements = (REAL *)realloc(elements,nelems*sizeof(REAL)),
  72.     memset(elements+old_nrows,0,(nrows-old_nrows)*sizeof(REAL));
  73.  
  74.                 // Vector is to shrink a lot (more than
  75.                 // 7/8 of the original size), reallocate
  76.   else if( old_nrows - nrows > (old_nrows>>3) )
  77.     elements = (REAL *)realloc(elements,nelems*sizeof(REAL));
  78.  
  79.                 // If the vector shrinks only a little, don't
  80.                 // bother reallocate
  81.   assert( elements != 0 );
  82. }
  83.  
  84. /*
  85.  *------------------------------------------------------------------------
  86.  *            Computing Vector norms
  87.  */
  88.  
  89.                 // Compute the 1-norm of the vector
  90.                 // SUM{ |v[i]| }
  91. double Vector::norm_1(void) const
  92. {
  93.   is_valid();
  94.  
  95.   register double norm = 0;
  96.   register REAL * vp;
  97.  
  98.   for(vp = elements; vp < elements + nelems; )
  99.     norm += ::abs(*vp++);
  100.  
  101.   return norm;
  102. }
  103.  
  104.                 // Compute the square of the 2-norm
  105.                 // SUM{ v[i]^2 }
  106. double Vector::norm_2_sqr(void) const
  107. {
  108.   is_valid();
  109.  
  110.   register double norm = 0;
  111.   register REAL * vp;
  112.  
  113.   for(vp = elements; vp < elements + nelems; )
  114.     norm += ::sqr(*vp++);
  115.  
  116.   return norm;
  117. }
  118.                 // Compute the infinity-norm of the vector
  119.                 // MAX{ |v[i]| }
  120. double Vector::norm_inf(void) const
  121. {
  122.   is_valid();
  123.  
  124.   register double norm = 0;
  125.   register REAL * vp;
  126.  
  127.   for(vp = elements; vp < elements + nelems; )
  128.     norm = ::max(norm,::abs(*vp++));
  129.  
  130.   return norm;
  131. }
  132.  
  133. /*
  134.  *------------------------------------------------------------------------
  135.  *        Multiplications specifically defined for vectors
  136.  */
  137.  
  138.                 // Compute the scalar product
  139. double operator * (const Vector& v1, const Vector& v2)
  140. {
  141.   are_compatible(v1,v2);
  142.   register REAL * v1p = v1.elements;
  143.   register REAL * v2p = v2.elements;
  144.   register double sum = 0;
  145.  
  146.   while( v1p < v1.elements + v1.nelems )
  147.     sum += *v1p++ * *v2p++;
  148.  
  149.   return sum;
  150. }
  151.  
  152.                     // "Inplace" multiplication
  153.                     // target = A*target
  154.                     // A needn't be a square one (the
  155.                     // target will be resized to fit)
  156. Vector& Vector::operator *= (const Matrix& A)
  157. {
  158.   A.is_valid();
  159.   is_valid();
  160.  
  161.   if( A.ncols != nrows || A.col_lwb != row_lwb )
  162.     A.info(), info(),
  163.     _error("matrices and vector above cannot be multiplied");
  164.  
  165.   const int old_nrows = nrows;
  166.   const REAL * old_vector = elements;    // Save the old vector elem
  167.   row_lwb = A.row_lwb;
  168.   assert( (nrows = A.nrows) > 0 );
  169.  
  170.   nelems = nrows;            // Allocate new vector elements
  171.   assert( (elements = (REAL *)malloc(nelems*sizeof(REAL))) != 0 );
  172.  
  173.   register REAL * tp = elements;    // Target vector ptr
  174.   register REAL * mp = A.elements;    // Matrix row ptr
  175.   while( tp < elements + nelems )
  176.   {
  177.     register double sum = 0;
  178.     for( register const REAL * sp = old_vector; sp < old_vector + old_nrows; )
  179.       sum += *sp++ * *mp, mp += A.nrows;
  180.     *tp++ = sum;
  181.     mp -= A.nelems -1;            // mp points to the beg of the next row
  182.   }
  183.   assert( mp == A.elements + A.nrows );
  184.  
  185.   free((REAL *)old_vector);
  186.   return *this;
  187. }
  188.  
  189.